package pl.edu.mimuw.mas.agent.behaviour.helicopter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import pl.edu.mimuw.mas.agent.HelicopterAgent;
import pl.edu.mimuw.mas.agent.behaviour.MutableTimedBehaviour;
import pl.edu.mimuw.mas.chart.Area;
import pl.edu.mimuw.mas.util.Move;
import pl.edu.mimuw.mas.util.MoveTrend;
import pl.edu.mimuw.mas.util.Position;
import pl.edu.mimuw.mas.util.PositionHelper;
import pl.edu.mimuw.mas.util.Time;

/**
 * Zachowanie patrolowania określonego terenu przez agenta typu helikopter.
 */
public class PatrolBehaviour extends MutableTimedBehaviour {
	private static final long serialVersionUID = -73679815823868067L;

	private static final int MOVE = 16;
	private static final int PRE_SEARCH = 32;
	private static final int POST_SEARCH = 64;
	
	private final Logger logger = LoggerFactory.getLogger(getClass());
	
	private Area searchArea;
	private Position dest; 
	private MoveTrend trend;
	private int status;
	
	private Position deerPosition;
	
	public PatrolBehaviour(HelicopterAgent agent, Area searchArea) {
		super(agent, Time.HELICOPTER_STEP);
		this.searchArea = searchArea;
		
		init();
	}

	public void init() {
		this.trend = MoveTrend.RIGHT;
		this.dest = new Position();
		this.status = MOVE;

		PositionHelper.getInitialSearchPosition(this.searchArea, this.dest);

		if (logger.isTraceEnabled()) {
			logger.trace("{}: Pierwszy cel (" + dest.x + ", " + dest.y + ")", myAgent.getName());
		}
	}
	
	protected void onTick() {
		HelicopterAgent ha = (HelicopterAgent) myAgent;
		switch (status) {
		case MOVE:		
			if (ha.getPosition().equals(dest)) {
				trend = PositionHelper.getNextSearchPosition(searchArea, ha.getPosition(), dest, trend);

				if (logger.isTraceEnabled()) {
					logger.trace("{}: Nowy cel (" + dest.x + ", " + dest.y + ")", ha.getName());
				}
			
				ha.setCheckColor();
				PositionHelper.flyRefresh(ha);
				status = PRE_SEARCH;			
			} else {
				int vx = dest.x - ha.getPosition().x;
				int vy = dest.y - ha.getPosition().y;
				int max = Math.max(Math.abs(vx), Math.abs(vy));

				PositionHelper.fly(ha, new Move((int) Math.round((double) vx / max), (int) Math.round((double) vy / max)));
			}			
			break;
			
		case PRE_SEARCH:
			deerPosition = PositionHelper.searchDeerInRange(ha);
			mutableBlock(Time.HELICOPTER_SEARCH);
			
			status = POST_SEARCH;
			break;
			
		case POST_SEARCH:
			if(deerPosition != null) {
				logger.info("{}: Chyba widziałem kotka...", ha.getName());				
				ha.doFollow();				
			} else {
				ha.setPatrolColor();
			}
			
			status = MOVE;
			break;
		}
	}
}
